home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / fg / fgmisc10 / menu.c < prev    next >
Text File  |  1993-10-25  |  16KB  |  604 lines

  1. /****************************************************************************\
  2. *                                                                            *
  3. *  menu.c -- menu management functions                                       *
  4. *                                                                            *
  5. \****************************************************************************/
  6.  
  7. #include "defs.h"
  8. #include <process.h>
  9.  
  10. CMD main_menu[] =
  11. {
  12.    submenu1, "FILE",       2,  76, 1, 3,
  13.    submenu2, "OPTIONS1",  80, 156, 2, 0,
  14.    submenu3, "OPTIONS2", 160, 236, 3, 1,
  15.    submenu4, "OPTIONS3", 240, 316, 0, 2,
  16. };
  17.  
  18. CMD menu1[] =
  19. {
  20.      load_files,  "load    ", 2,  76, 1, 5,
  21.   null_function,  "save",     2,  76, 2, 0,
  22.   null_function,  "nothing",  2,  76, 3, 1,
  23.   null_function,  "whatever", 2,  76, 4, 2,
  24.           shell,  "Shell",    2,  76, 5, 3,
  25.    exit_program,  "Exit",     2,  76, 0, 4,
  26. };
  27.  
  28. CMD menu2[] =
  29. {
  30.    null_function, "edit",    80, 156, 1, 2,
  31.    null_function, "load",    80, 156, 2, 0,
  32.    null_function, "save",    80, 156, 0, 1,
  33. };
  34.  
  35. CMD menu3[] =
  36. {
  37.    null_function, "this     ",160,236, 1, 3,
  38.    null_function, "that",     160,236, 2, 0,
  39.    null_function, "the other",160,236, 3, 1,
  40.    null_function, "thing",    160,236, 0, 2,
  41. };
  42.  
  43. CMD menu4[] =
  44. {
  45.    null_function,  "edit ",   240, 316, 1, 2,
  46.    null_function,  "load",    240, 316, 2, 0,
  47.    null_function,  "save",    240, 316, 0, 1,
  48. };
  49.  
  50. int selection = 0;
  51. FILE *tstream;
  52.  
  53. /****************************************************************************\
  54. *                                                                            *
  55. *  highlight option -- highlight an option on the main menu                  *
  56. *                                                                            *
  57. \****************************************************************************/
  58.  
  59. void highlight_option(int n)
  60. {
  61.    int y;
  62.  
  63.    y = MENU_TOP + 8;
  64.  
  65.    fg_setcolor(black);
  66.    fg_rect(main_menu[n].x1,main_menu[n].x2,MENU_TOP,MENU_BOTTOM-1);
  67.    fg_setcolor(white);
  68.    center_bstring(main_menu[n].menu_item,main_menu[n].x1,main_menu[n].x2,y);
  69. }
  70.  
  71. /****************************************************************************\
  72. *                                                                            *
  73. *  horizontal_menu -- main menu containing submenus                          *
  74. *                                                                            *
  75. \****************************************************************************/
  76.  
  77. horizontal_menu(CMD cmdtab[],int n,int current)
  78. {
  79.    register int i, k;
  80.    int c;
  81.    int found, new;
  82.    int ymin, ymax;
  83.    char l;
  84.  
  85.    if (current >= abs(n))
  86.       return(ERR);
  87.  
  88.    ymin = MENU_TOP;
  89.    ymax = ymin + 10;
  90.  
  91.    fg_mousevis(OFF);
  92.  
  93.    /* set up list of options */
  94.  
  95.    if (n < 0)
  96.    {
  97.       for (i = 0; i < abs(n); i++)
  98.       {
  99.          fg_setcolor(white);
  100.          fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
  101.          fg_setcolor(black);
  102.          center_bstring(cmdtab[i].menu_item,cmdtab[i].x1,cmdtab[i].x2,ymax-2);
  103.       }
  104.       fg_save(0,319,MENU_TOP,MENU_BOTTOM);
  105.    }
  106.  
  107.    /* highlight current option */
  108.  
  109.    i = current;
  110.  
  111.    fg_setcolor(black);
  112.    fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
  113.    fg_setcolor(white);
  114.    center_bstring(cmdtab[i].menu_item,cmdtab[i].x1,cmdtab[i].x2,ymax-2);
  115.  
  116.    /* if we're just displaying the menu options, return */
  117.  
  118.    if (n < 0) return(OK);
  119.  
  120.    fg_mousevis(ON);
  121.  
  122.    /* choose an option */
  123.  
  124.    new = current;
  125.    fg_setnum(OFF);
  126.    flushkey();
  127.  
  128.    for(;;)
  129.    {
  130.       /* activate the corresponding vertical menu */
  131.  
  132.       main_option = i;
  133.       c = (*cmdtab[i].menu_func)();
  134.  
  135.       /* cycle through choices */
  136.  
  137.       if (c == LEFT_ARROW || c == BS)
  138.          new = cmdtab[i].prev;
  139.  
  140.       else if (c == RIGHT_ARROW || c == SPACEBAR)
  141.          new = cmdtab[i].next;
  142.  
  143.       else if (c >= 0 && c <= n)
  144.          new = c;
  145.  
  146.       else if (c == ESC)
  147.       {
  148.          exit_program();
  149.          return(i);
  150.       }
  151.  
  152.       else if (isalpha(c))
  153.       {
  154.           c = tolower(c);
  155.           found = FALSE;
  156.           for (k = i+1; k < n; k++)
  157.           {
  158.              l = first_nonblank(cmdtab[k].menu_item);
  159.              if (c == tolower((int)l))
  160.              {
  161.                 found = TRUE;
  162.                 break;
  163.              }
  164.           }
  165.           if (!found)
  166.           {
  167.              for (k = 0; k <= i; k++)
  168.              {
  169.                 l = first_nonblank(cmdtab[k].menu_item);
  170.                 if (c == (char)tolower((int)l))
  171.                 {
  172.                    found = TRUE;
  173.                    break;
  174.                 }
  175.              }
  176.          }
  177.          if (found)
  178.             new = k;
  179.          else
  180.          {
  181.             main_option = i;
  182.             return(i);
  183.          }
  184.       }
  185.       else
  186.       {
  187.          main_option = i;
  188.          return(i);
  189.       }
  190.  
  191.       if (i != new)
  192.       {
  193.          /* unmark previous option */
  194.  
  195.          fg_mousevis(OFF);
  196.          fg_setcolor(white);
  197.          fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
  198.          fg_setcolor(black);
  199.          center_bstring(cmdtab[i].menu_item,cmdtab[i].x1,cmdtab[i].x2,ymax-2);
  200.  
  201.          /* mark new option */
  202.  
  203.          i = new;
  204.          fg_setcolor(black);
  205.          fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
  206.          fg_setcolor(white);
  207.          center_bstring(cmdtab[i].menu_item,cmdtab[i].x1,cmdtab[i].x2,ymax-2);
  208.          fg_mousevis(ON);
  209.       }
  210.    }
  211. }
  212.  
  213. /****************************************************************************\
  214. *                                                                            *
  215. *  submenus                                                                  *
  216. *                                                                            *
  217. \****************************************************************************/
  218.  
  219. submenu1()
  220. {
  221.    return(vertical_menu(menu1,0,6));
  222. }
  223. submenu2()
  224. {
  225.    return(vertical_menu(menu2,1,3));
  226. }
  227. submenu3()
  228. {
  229.    return(vertical_menu(menu3,2,4));
  230. }
  231. submenu4()
  232. {
  233.    return(vertical_menu(menu4,3,3));
  234. }
  235.  
  236. /****************************************************************************\
  237. *                                                                            *
  238. *  vertical_menu -- submenu off main menu                                    *
  239. *                                                                            *
  240. \****************************************************************************/
  241.  
  242. vertical_menu(CMD cmdtab[],int index,int n)
  243. {
  244.    register int i, j, k;
  245.    int found, new;
  246.    int height;
  247.    int left, right;
  248.    int string_x;
  249.    int x1, x2, y1, y2;
  250.    int ymin, ymax;
  251.    int count;
  252.    char c, l;
  253.    unsigned char key, aux;
  254.  
  255.    /* height in pixels of an individual menu item */
  256.  
  257.    height = 10;
  258.  
  259.    /* the first menu item determines the x coordinate for the other items */
  260.  
  261.    string_x = get_center(cmdtab[0].menu_item,cmdtab[0].x1,cmdtab[0].x2);
  262.  
  263.    /* define the menu extremes */
  264.  
  265.    x1 = cmdtab[0].x1 - 1;
  266.    x2 = cmdtab[0].x2 + 3;
  267.    y1 = MENU_BOTTOM+1;
  268.    y2 = MENU_BOTTOM + n*height + 1;
  269.  
  270.    /* define the associated horizontal mouse limits */
  271.  
  272.    if (mouse)
  273.    {
  274.       left  = mouse_limits[index];
  275.       right = mouse_limits[index+1] - 2;
  276.    }
  277.  
  278.    /* display the vertical menu if necessary */
  279.  
  280.    if (redraw)
  281.    {
  282.       /* do this stuff on the hidden page to make it look faster */
  283.  
  284.       fg_setpage(HIDDEN);
  285.  
  286.       /* draw the menu outline and the shadow around it */
  287.  
  288.       fg_mousevis(OFF);
  289.       fg_setcolor(white);
  290.       fg_box(x1,x2-2,y1,y2-1);
  291.       
  292.       fg_setcolor(dkblue);
  293.       fg_rect(x1+1,x2,y2+1,y2+1);
  294.       fg_rect(x1+2,x2,y2+2,y2+2);
  295.       fg_rect(x2-1,x2,y1,y2+2);
  296.  
  297.       fg_setcolor(black);
  298.       fg_box(x1,x2-2,y1,y2);
  299.  
  300.       /* set up list of options */
  301.  
  302.       ymax = MENU_BOTTOM;
  303.       for (i = 0; i < n; i++)
  304.       {
  305.          ymin = ymax + 1;
  306.          ymax = ymin + height-1;
  307.          fg_setcolor(white);
  308.          fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
  309.          fg_setcolor(black);
  310.          put_bstring(cmdtab[i].menu_item,string_x,ymax-2);
  311.       }
  312.  
  313.       /* highlight first or previously selected option */
  314.  
  315.       i = selection;
  316.       ymin = MENU_BOTTOM + i*height;
  317.       ymax = ymin + height;
  318.       fg_setcolor(black);
  319.       fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
  320.       fg_setcolor(white);
  321.       put_bstring(cmdtab[i].menu_item,string_x,ymax-2);
  322.  
  323.       /* restore the menu to the visual page */
  324.  
  325.       fg_setpage(VISUAL);
  326.       fg_restore(x1,x2,y1,y2+2);
  327.       redraw = FALSE;
  328.       fg_setpage(HIDDEN);
  329.  
  330.       /* clear the hidden page under the menu */
  331.  
  332.       fg_setcolor(blue);
  333.       fg_rect(x1,x2,y1,y2+2);
  334.  
  335.       fg_setpage(VISUAL);
  336.       fg_mousevis(ON);
  337.    }
  338.  
  339.    /* choose an option */
  340.  
  341.    i = selection;
  342.    new = i;
  343.    fg_setnum(OFF);
  344.    flushkey();
  345.  
  346.    for(;;)
  347.    {
  348.       /* read a keystroke */
  349.  
  350.       fg_mousevis(ON);
  351.       fg_waitfor(1);
  352.       fg_intkey(&key,&aux);
  353.  
  354.       /* if using a mouse, check its position */
  355.  
  356.       if (mouse && key+aux == 0)
  357.       {
  358.          fg_mousebut(1,&count,&xmouse,&ymouse);
  359.  
  360.          if (count > 0)
  361.          {
  362.             if (BETWEEN(xmouse,x1,x2) && BETWEEN(ymouse,y1,y2-2))
  363.             {
  364.                new = (ymouse - y1) / height;
  365.  
  366.                /* check if this is the second click of a double click */
  367.  
  368.                if (i == new)
  369.                   key = CR;
  370.             }
  371.             else if (!BETWEEN(xmouse,left,right) && BETWEEN(ymouse,MENU_TOP,y1-1))
  372.             {
  373.                fg_mousevis(OFF);
  374.                fg_restore(0,xlimit,MENU_BOTTOM,ylimit);
  375.                redraw = TRUE;
  376.                selection = 0;
  377.                for (j = 0; j <= ITEMS; j++)
  378.                {
  379.                  if (BETWEEN(xmouse,mouse_limits[j],mouse_limits[j+1]))
  380.                     return(j);
  381.                }
  382.             }
  383.             else
  384.             {
  385.                fg_mousevis(OFF);
  386.                fg_restore(0,xlimit,MENU_BOTTOM,ylimit);
  387.                redraw = TRUE;
  388.                selection = 0;
  389.                return(-1);
  390.             }
  391.          }
  392.       }
  393.  
  394.       /* cycle through choices */
  395.  
  396.       if (aux == UP_ARROW || key == BS)
  397.          new = cmdtab[i].prev;
  398.       else if (aux == DOWN_ARROW || key == SPACEBAR)
  399.          new = cmdtab[i].next;
  400.  
  401.       else if (aux == HOME || aux == PGUP)
  402.          new = 0;
  403.  
  404.       else if (aux == END || aux == PGDN)
  405.          new = n - 1;
  406.  
  407.       else if (aux == LEFT_ARROW || aux == RIGHT_ARROW)
  408.       {
  409.          fg_mousevis(OFF);
  410.          fg_restore(0,xlimit,MENU_BOTTOM,ylimit);
  411.          redraw = TRUE;
  412.          selection = 0;
  413.          return((int)aux);
  414.       }
  415.  
  416.       /* pick one choice */
  417.  
  418.       else if (key == CR)
  419.       {
  420.          (*cmdtab[i].menu_func)();
  421.          wait_for_mouse_buttons();
  422.          selection = i;
  423.          return(index);
  424.       }
  425.  
  426.       else if (key == ESC)
  427.       {
  428.          selection = 0;
  429.          return(ESC);
  430.       }
  431.       else if (isalpha((int)key))
  432.       {
  433.           c = (char)tolower((int)key);
  434.           found = FALSE;
  435.           for (k = i+1; k < n; k++)
  436.           {
  437.              l = first_nonblank(cmdtab[k].menu_item);
  438.              if (c == (char)tolower((int)l))
  439.              {
  440.                 found = TRUE;
  441.                 break;
  442.              }
  443.           }
  444.           if (!found)
  445.           {
  446.              for (k = 0; k <= i; k++)
  447.              {
  448.                 l = first_nonblank(cmdtab[k].menu_item);
  449.                 if (c == (char)tolower((int)l))
  450.                 {
  451.                    found = TRUE;
  452.                    break;
  453.                 }
  454.              }
  455.          }
  456.          if (found)
  457.             new = k;
  458.          else
  459.          {
  460.             redraw = TRUE;
  461.             return(-1);
  462.          }
  463.       }
  464.       else if (key+aux > 0) /* any other key */
  465.       {
  466.          redraw = TRUE;
  467.          return(-1);
  468.       }
  469.  
  470.       if (i != new)
  471.       {
  472.          /* unmark previous option */
  473.  
  474.          ymin = MENU_BOTTOM + i*height;
  475.          ymax = ymin + height;
  476.          fg_mousevis(OFF);
  477.          fg_setcolor(white);
  478.          fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
  479.          fg_setcolor(black);
  480.          put_bstring(cmdtab[i].menu_item,string_x,ymax-2);
  481.  
  482.          /* mark new option */
  483.  
  484.          i = new;
  485.          ymin = MENU_BOTTOM + i*height;
  486.          ymax = ymin + height;
  487.          fg_setcolor(black);
  488.          fg_rect(cmdtab[i].x1,cmdtab[i].x2,ymin,ymax);
  489.          fg_setcolor(white);
  490.          put_bstring(cmdtab[i].menu_item,string_x,ymax-2);
  491.  
  492.          /* move mouse cursor to the new option */
  493.  
  494.          if (mouse)
  495.          {
  496.             fg_mousepos(&xmouse,&ymouse,&buttons);
  497.             if (BETWEEN(xmouse,x1,x2)) fg_mousemov(xmouse,(ymin+ymax)/2);
  498.             fg_mousevis(ON);
  499.          }
  500.       }
  501.    }
  502. }
  503.  
  504. null_function()
  505. {
  506.    return(OK);
  507. }
  508.  
  509. /****************************************************************************\
  510. *                                                                            *
  511. *  exit_program -- from menu                                                 *
  512. *                                                                            *
  513. \****************************************************************************/
  514.  
  515. exit_program()
  516. {
  517.    quit_graphics();
  518.    return(0);
  519. }
  520.  
  521. /****************************************************************************\
  522. *                                                                            *
  523. *  first_nonblank -- find first character that is not a blank                *
  524. *                                                                            *
  525. \****************************************************************************/
  526.  
  527. char first_nonblank(char *string)
  528. {
  529.    register int i;
  530.    char c;
  531.  
  532.    i = 0;
  533.    for(;;)
  534.    {
  535.       c = string[i++];
  536.       if (c == 0)
  537.          return(0);
  538.       else if (c > 32)
  539.          return(c);
  540.    }
  541. }
  542.  
  543. /****************************************************************************\
  544. *                                                                            *
  545. *  shell -- create a DOS command shell                                       *
  546. *                                                                            *
  547. \****************************************************************************/
  548.  
  549. shell()
  550. {
  551.    int count;
  552.  
  553.    fg_mousepos(&xmouse,&ymouse,&buttons);
  554.    fg_mousevis(0);
  555.    fg_setmode(3);
  556.    fg_mouseini();
  557.    fg_reset();
  558.  
  559.    /* spawn the DOS command shell */
  560.  
  561.    printf("\nType 'Exit' to return to the menu.\n");
  562.    spawnlp(P_WAIT,"command.com",NULL);
  563.  
  564.    /* upon return from DOS, restore the video context */
  565.  
  566.    fg_setmode(22);
  567.    fg_setpage(0);
  568.    fg_setvpage(0);
  569.    fg_sethpage(1);
  570.    init_mouse();
  571.    fg_mousevis(0);
  572.  
  573.    /* redraw the screen */
  574.  
  575.    draw_screen();
  576.    redraw = TRUE;
  577.  
  578.    fg_mousemov(xmouse,ymouse);
  579.  
  580.    fg_mousebut(1,&count,&xmouse,&ymouse);
  581.    fg_mousebut(2,&count,&xmouse,&ymouse);
  582.  
  583.    return(OK);
  584. }
  585.  
  586. /****************************************************************************\
  587. *                                                                            *
  588. *  wait_for_mouse_buttons -- wait until no mouse buttons are pressed         *
  589. *                                                                            *
  590. \****************************************************************************/
  591.  
  592. void wait_for_mouse_buttons()
  593. {
  594.    int buttons;
  595.    int x, y;
  596.  
  597.    if (mouse)
  598.    {
  599.       do
  600.          fg_mousepos(&x,&y,&buttons);
  601.       while (buttons&3);
  602.    }
  603. }
  604.